package main

import (
	"clouddisk/internal/file"
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"
)

type Config struct {
	Dsn          string
	RegistHost   string
	BaseService  string
	InstanceName string
	InstanceHost string
	ListenPort   string
	StorePath    string
}

func initConfig() *Config {
	defaultPort := "8080"
	cfg := &Config{
		Dsn:          "root@tcp(localhost:3306)/Alpaca?parseTime=true&loc=Local",
		RegistHost:   "localhost:2379",
		BaseService:  "/service",
		InstanceName: "/file_service/instance",
		InstanceHost: "localhost:8080",
		ListenPort:   defaultPort,
		StorePath:    "/home/alpaca/clouddisk/back",
	}

	// 定义命令行参数绑定
	flag.StringVar(&cfg.Dsn, "dsn", cfg.Dsn, "数据库连接字符串\n格式: username:password@protocol(address)/dbname")
	flag.StringVar(&cfg.RegistHost, "regist-host", cfg.RegistHost, "服务注册中心地址")
	flag.StringVar(&cfg.BaseService, "service", cfg.BaseService, "服务监控根目录")
	flag.StringVar(&cfg.InstanceName, "name", cfg.InstanceName, "当前实例名称")
	flag.StringVar(&cfg.InstanceHost, "host", cfg.InstanceHost, "当前实例的外部访问地址")
	flag.StringVar(&cfg.ListenPort, "port", cfg.ListenPort, fmt.Sprintf("服务监听端口 (默认: %v)", defaultPort))
	flag.StringVar(&cfg.StorePath, "store", cfg.StorePath, "文件存储根路径")

	// 自定义帮助信息
	flag.Usage = func() {
		fmt.Fprintf(flag.CommandLine.Output(), "文件服务启动程序\n\n")
		fmt.Fprintf(flag.CommandLine.Output(), "用法: %s [选项]\n\n", os.Args[0])
		fmt.Fprintln(flag.CommandLine.Output(), "选项:")
		flag.PrintDefaults()

		fmt.Fprintln(flag.CommandLine.Output(), "\n环境变量:")
		fmt.Fprintln(flag.CommandLine.Output(), "  APP_DSN          数据库连接字符串")
		fmt.Fprintln(flag.CommandLine.Output(), "  APP_REGIST_HOST  注册中心地址")
		fmt.Fprintln(flag.CommandLine.Output(), "  APP_PORT         监听端口")

		fmt.Fprintln(flag.CommandLine.Output(), "\n示例:")
		fmt.Fprintf(flag.CommandLine.Output(), "  %s -port 8080 -store /data/files\n", os.Args[0])
	}

	flag.Parse()

	// 配置文件读取

	// 最终配置验证
	if err := validateConfig(cfg); err != nil {
		fmt.Printf("配置错误: %v\n\n", err)
		flag.Usage()
		os.Exit(1)
	}

	return cfg
}

func validateConfig(cfg *Config) error {
	// 监听端口验证
	port, err := strconv.Atoi(cfg.ListenPort)
	if err != nil {
		return fmt.Errorf("字符串转换失败")
	}
	if port < 1 || port > 65535 {
		return fmt.Errorf("端口号必须在 1-65535 之间")
	}

	// 数据库连接字符串验证
	if cfg.Dsn == "" {
		return fmt.Errorf("数据库连接字符串不能为空")
	}

	// 注册中心地址验证
	if cfg.RegistHost == "" {
		return fmt.Errorf("注册中心地址不能为空")
	}

	// 服务名称验证
	if cfg.BaseService == "" {
		return fmt.Errorf("服务名称不能为空")
	}

	// 存储路径验证
	if cfg.StorePath == "" {
		return fmt.Errorf("存储路径不能为空")
	}

	return nil
}

func main() {
	log.SetFlags(log.Llongfile | log.Ltime)

	cfg := initConfig()

	server, err := file.NewFileServerBuilder().WithMysqlObject(cfg.Dsn).
		WithRegisterObject(cfg.RegistHost, cfg.BaseService+cfg.InstanceName, cfg.InstanceHost).
		WithRPCObject(cfg.ListenPort, cfg.StorePath).
		Build()

	if err != nil {
		panic(err)
	}

	err = server.Serve()
	if err != nil {
		panic(err)
	}
	log.Println("程序已退出")
}
